package com.ego.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.TypeReference;
import com.ego.common.constant.OrderConstant;
import com.ego.common.constant.SystemConstant;
import com.ego.common.exception.GlobalException;
import com.ego.common.to.member.MemberTo;
import com.ego.common.util.Result;
import com.ego.common.vo.member.MemberReceiveAddressVo;
import com.ego.product.feign.MemberFeign;
import com.ego.product.interceptor.LoginInterceptor;
import com.ego.product.service.CartService;
import com.ego.product.service.OrderService;
import com.ego.common.vo.product.CartVo;
import com.ego.product.vo.order.OrderConfirmVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @program: ego
 * @description:
 * @author: KamTang
 * @create: 2022-12-20 14:40
 **/
@Service("orderService")
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MemberFeign memberFeign;
    @Autowired
    private CartService cartService;
    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public OrderConfirmVo confirm() throws ExecutionException, InterruptedException {
        MemberTo member = LoginInterceptor.threadLocal.get();
        // 获取之前的请求
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 查询会员所有收货地址列表
        CompletableFuture<List<MemberReceiveAddressVo>> addressTask = CompletableFuture.supplyAsync(() -> {
            // 每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<MemberReceiveAddressVo> memberReceiveAddress = new ArrayList<>();
            Long memberId = member.getId();
            try {
                Result mResult = memberFeign.gets(memberId);
                if (mResult.getCode() == SystemConstant.Status.SUCCESS.getCode()) {
                    memberReceiveAddress = mResult.getData("memberReceiveAddressVos",
                            new TypeReference<List<MemberReceiveAddressVo>>() {
                            });
                }
            } catch (Exception e) {
                throw new GlobalException("远程调用会员服务失败", SystemConstant.Status.FEIGN_EXCEPTION.getCode());
            }
            return memberReceiveAddress;
        }, executor);

        CompletableFuture<List<CartVo.CartItem>> cartItemTask = CompletableFuture.supplyAsync(() -> {
            // 每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);

            // TODO 这里没有远程调用，所以cart的拦截器没有起到作用，基于现在的项目结构，暂时将order获取的用户信息传递给cart作为参数
            // 获取当前用户购物项信息
            return cartService.getCurrentUserCartItem(member.getId());
        }, executor);
        CompletableFuture.allOf(addressTask, cartItemTask).get();
        OrderConfirmVo orderConfirmVo = buildOrderConfirm(addressTask.get(), cartItemTask.get());

        // 防重令牌
        String uuid = UUID.randomUUID().toString().replace("-", "");
        stringRedisTemplate.opsForValue().set(OrderConstant.ORDER_TOKEN_PREFIX + member.getId(), uuid, 30, TimeUnit.MINUTES);
        orderConfirmVo.setOrderToken(uuid);

        return orderConfirmVo;
    }

    private OrderConfirmVo buildOrderConfirm(List<MemberReceiveAddressVo> addresses, List<CartVo.CartItem> cartItems) {
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();
        orderConfirmVo.setAddressVos(addresses);
        if (!CollectionUtils.isEmpty(cartItems)) {
            // 将cartItem转化成orderItem
            List<OrderConfirmVo.OrderItemVo> orderItemVos = cartItems.stream().map(this::buildOrderItem)
                    .collect(Collectors.toList());
            orderConfirmVo.setOrderItems(orderItemVos);
        }
        return orderConfirmVo;
    }

    private OrderConfirmVo.OrderItemVo buildOrderItem(CartVo.CartItem cartItem) {
        OrderConfirmVo.OrderItemVo orderItemVo = new OrderConfirmVo.OrderItemVo();
        BeanUtil.copyProperties(cartItem, orderItemVo);
        if (!CollectionUtils.isEmpty(cartItem.getSkuAttrs())) {
            orderItemVo.setSkuAttrs(cartItem.getSkuAttrs());
        }
        return orderItemVo;
    }
}
